import type {
	IAbility,
	IActionResult,
	IContext,
	IParam,
	IUIService,
	IViewLogicHelper,
	IViewLogicInput,
} from '@/core';
import { deepCopy } from '@/core';
import { transformDoData } from '@/core';

/**
 * 视图逻辑辅助类
 */
export class ViewLogicHelper implements IViewLogicHelper {
	/**
	 * 单例服务
	 *
	 * @protected
	 * @static
	 * @type {IViewLogicHelper}
	 * @memberof ViewLogicHelper
	 */
	private static service: IViewLogicHelper;

	/**
	 * 获取实例
	 *
	 * @static
	 * @return {*}  {IViewLogicHelper}
	 * @memberof ViewLogicHelper
	 */
	static getInstance(): IViewLogicHelper {
		if (!this.service) {
			this.service = new ViewLogicHelper();
		}
		return this.service;
	}

	/**
	 * 执行视图逻辑
	 *
	 * @template T
	 * @param {IContext} context
	 * @param {IParam} viewParams
	 * @param {IParam[]} data
	 * @param {MouseEvent} event
	 * @param {T} ability
	 * @param {IViewLogicInput} inputParams
	 * @return {*}  {Promise<IActionResult>}
	 * @memberof ViewLogicHelper
	 */
	public async executeViewLogic<T extends IAbility>(
		context: IContext,
		viewParams: IParam,
		data: IParam[],
		event: MouseEvent,
		ability: T,
		inputParams: IViewLogicInput
	): Promise<IActionResult> {
		const { actionTag, predefinedType } = inputParams;
		const {
			context: tempContext,
			viewParams: tempViewParams,
			data: tempData,
		} = this.beforeHandle<T>(ability, context, viewParams, data);
		if (predefinedType) {
			return await App.getGlobalActionHelper().executeUIAction(
				predefinedType,
				tempContext,
				tempViewParams,
				tempData,
				event,
				ability
			);
		}
		const { actionDECodeName } = inputParams;
		if (actionDECodeName) {
			const uiService: IUIService = await App.getUIService(
				actionDECodeName,
				context
			);
			if (!uiService) {
				return { ok: false, data: null };
			}
			return await uiService.executeUIAction(
				actionTag,
				tempContext,
				tempViewParams,
				tempData,
				event,
				ability
			);
		}
		return { ok: false, data: null };
	}

	/**
	 * 处理之前
	 *
	 * @private
	 * @template T
	 * @param {T} ability
	 * @param {IContext} context
	 * @param {IParam} viewParams
	 * @param {IParam[]} data
	 * @return {*}  {{
	 *     context: IContext;
	 *     viewParams: IParam;
	 *     data: IParam[];
	 *   }}
	 * @memberof ViewLogicHelper
	 */
	private beforeHandle<T extends IAbility>(
		ability: T,
		context: IContext,
		viewParams: IParam,
		data: IParam[]
	): {
		context: IContext;
		viewParams: IParam;
		data: IParam[];
	} {
		const _context = deepCopy(context);
		const _viewParams = deepCopy(viewParams);
		const tempData = data && data.length > 0 ? data[0] : {};
		const model = ability.getModel();
		//  上下文中无当前数据主键，且数据中有，则添加
		if (
			model &&
			model.entityCodeName &&
			tempData &&
			tempData[model.entityCodeName.toLowerCase()] &&
			!_context.hasOwnProperty(model.entityCodeName.toLowerCase())
		) {
			Object.assign(_context, {
				[model.entityCodeName.toLowerCase()]:
					tempData[model.entityCodeName.toLowerCase()],
			});
		}
		//  转换数据，从VO转换成DO
		const _data = transformDoData<IParam[]>(data);
		return { context: _context, viewParams: _viewParams, data: _data };
	}
}
